'''
This file is part of DopplerShift.

    DopplerShift is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DopplerShift is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DopplerShift.  If not, see <http://www.gnu.org/licenses/>.
'''
import time
import logging
logger = logging.getLogger()
class DSItem(object):
    _expired_time = 0
    _contained = None
    _key = None
    parent = None
    red_child = None
    black_child = None
    def __init__(self, contained_object, object_key, expire_time=None):
        self._key = object_key
        self._contained = contained_object
        self._expired_time = expire_time
    def isExpired(self, current_time):
        if self._expired_time == None:
            return False
        if self._expired_time <= current_time:
            return True
        return False
    def get(self):
        return self._contained
    def getExpireTime(self):
        return self._expired_time
    def put(self, item):
        iet = item.getExpireTime()
        if iet < self._expired_time:
            if not self.parent is None:
                p = self.parent
            self.parent = item
            item.black_child = self
        elif iet == self._expired_time:
            if not self.red_child is None:
                r = self.red_child
                item.red_child = r
            self.red_child = item
        else:
            if self.black_child is None:
                self.black_child = item
            self.black_child.put(item)
    def getKey(self):
        return self._key

class DSContainerBase(object):
    _incrementor = 0
    def __init__(self):
        self._contained_object = {}
    def set(self, objectData, expire=None, salt_key=''):
        now = time.time()
        if expire != None:
            expire += now
        self._incrementor += 1
        obj_key = "%s_%s_%s"%(objectData.__class__.__name__, salt_key, self._incrementor)
        
        self._contained_object[obj_key ]= DSItem(objectData, obj_key, expire)
        return obj_key
    def clean(self):
        now = time.time()
        for el in self._contained_object.keys():
            if self._contained_object[el].isExpired(now):
                self.remove(el)
    def remove(self, obj_key):
        if obj_key in self._contained_object:
            self._contained_object.pop(obj_key)
            
    def get(self, obj_key):
        if obj_key in self._contained_object:
            return self._contained_object[obj_key].get()
        return None
    def pop(self, obj_key):
        if obj_key in self._contained_object:
            return self._contained_object.pop(obj_key)
        return None

class DSContainerLinear(DSContainerBase):
    def __init__(self):
        self._container_index = []
        DSContainerBase.__init__(self)
    def set(self, objectData, expire=None, salt_key=''):
        k = DSContainerBase.set(self, objectData, expire, salt_key)
        dsItem = self._contained_object.get(k)
        self._container_index.append(dsItem)
        dsItem.index_pos = len(self._container_index) - 1
    def clean(self):
        now = time.time()
        while len(self._container_index) > 0 and self._container_index[0].isExpired(now):
            d = self._container_index.pop(0)
            self.remove(d.getKey())
    def pop(self, obj_key):
        p = DSContainerBase.pop(self, obj_key)
        if not p is None:
            self._container_index.pop(p.index_pos)
        return p
            
class DSContainerTree(DSContainerBase):
    def __init__(self):
        self._container_index = None
        DSContainerBase.__init__(self)
    def set(self, objectData, expire=None, salt_key=''):
        k = DSContainerBase.set(objectData, expire, salt_key)
        dsItem = self.get(k)
        self._set(dsItem)
    def _set(self, item):
        if self._container_tree is None:
            self._container_tree = item
            return
    def _find_in_tree(self, current_item, item):
        if current_item.getExpireTime() > item.getExpireTime():
            p = current_item.parent
            current_item.parent = item
            item.parent = p
            current_item

class DSContainer(DSContainerBase):
    '''
    
    '''